Skip to content

feat(gitlab): authenticate self-hosted GitLab via ASPECT_GITLAB_TOKEN#1237

Open
b3cramer wants to merge 1 commit into
mainfrom
feat/gitlab-self-hosted-auth
Open

feat(gitlab): authenticate self-hosted GitLab via ASPECT_GITLAB_TOKEN#1237
b3cramer wants to merge 1 commit into
mainfrom
feat/gitlab-self-hosted-auth

Conversation

@b3cramer

@b3cramer b3cramer commented Jun 16, 2026

Copy link
Copy Markdown
Member

Problem

#1235 made the GitLab API base configurable, but that alone doesn't unblock self-hosted GitLab. The three GitLab features (GitlabCommitStatuses, GitlabStatusComments, GitlabLintComments) only ever obtained a token by minting through the Aspect GitLab App, which is an OAuth Application registered on gitlab.com. A token minted there can't authenticate against another instance, so pointing ASPECT_GITLAB_API_URL / CI_API_V4_URL at a self-hosted host would 401 at the first API call.

Every feature call was also hard-coded to auth_kind = "bearer".

Change

Add gitlab_token_cache.resolve_token(), which returns (token, auth_kind):

  • When ASPECT_GITLAB_TOKEN (a personal / group / project access token with api scope) is set, it short-circuits the mint and selects the PRIVATE-TOKEN header convention (auth_kind = "private_token"). No minting, no per-process caching. This is the self-hosted path.
  • Otherwise it falls back to the existing Aspect-App bearer mint via get_or_mint, unchanged.

The resolved auth_kind is threaded through every gitlab.* call in the three features (alongside the api_base added in #1235), replacing the previously hard-coded "bearer".

The remaining self-hosted touch points were already host-correct via native GitLab CI vars and need no change: build/Web-UI URLs derive from CI_JOB_URL (ci.axl) and REPO_URL from CI_SERVER_URL (build_metadata.axl).

⚠️ Validation status

This is unit-tested plumbing, NOT validated against a live GitLab instance. No test in this PR makes an HTTP request to any GitLab API — not self-hosted, not gitlab.com. What's covered is the env→(token, auth_kind) / env→api_base resolution logic and that the builtin graph loads. The claim that commit statuses / MR notes / discussions actually authenticate and post via PRIVATE-TOKEN against a self-hosted host is unverified and needs a live integration test before we tell customers it works.


Changes are visible to end-users: yes

  • Searched for relevant documentation and updated as needed: documented in aspect-build/site#1072 (held as draft pending live validation)

  • Breaking change (forces users to change their own code or config): no — gitlab.com via the Aspect App is unchanged when ASPECT_GITLAB_TOKEN is unset

  • Suggested release notes appear below: yes

  • Adds an ASPECT_GITLAB_TOKEN path (sent as PRIVATE-TOKEN) and ASPECT_GITLAB_API_URL host override so the GitLab features can target a non-gitlab.com instance. Not yet validated end-to-end against a live self-hosted instance — do not announce as supported until that lands.

Test plan

Covered:

  • resolve_token unit cases in lib/gitlab_test.axl (explicit-token value + private_token selection; mint-fallback returns (None, "bearer")).
  • aspect dev test-gitlab-clientgitlab.axl smoke: OK; aspect dev test-gitlab-featuresOK; aspect tests axl790 tests passed.

NOT covered (follow-up before declaring self-hosted support):

  • No request against any live GitLab API. Need an integration run with a real ASPECT_GITLAB_TOKEN against a real MR (gitlab.com is a valid proxy for the PRIVATE-TOKEN code path; a true self-hosted instance is the ideal) confirming a commit status, MR note, and inline discussion actually post.

Builds on #1235.

The API-base override alone wasn't enough for self-hosted GitLab: the
features only obtained a token by minting through the Aspect GitLab App,
which is registered on gitlab.com and can't authenticate against another
instance.

Add gitlab_token_cache.resolve_token(), which returns (token, auth_kind):
when ASPECT_GITLAB_TOKEN (a personal/group/project access token) is set it
short-circuits the mint and uses the PRIVATE-TOKEN header convention;
otherwise it falls back to the Aspect-App bearer mint as before. Thread the
resolved auth_kind through every gitlab.* call in the three features
alongside api_base, replacing the previously hard-coded "bearer".

With this, self-hosted GitLab works end to end: CI_API_V4_URL (or an
explicit ASPECT_GITLAB_API_URL) selects the host, ASPECT_GITLAB_TOKEN
authenticates against it, and build/Web-UI URLs already derive from the
native CI_SERVER_URL / CI_JOB_URL (build_metadata.axl, ci.axl).

Adds resolve_token unit tests to lib/gitlab_test.axl.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a2a298aaef

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

return True
auth_reason = {}
token = gitlab_token_cache.get_or_mint(
token, auth_kind = gitlab_token_cache.resolve_token(

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Don't pass GitLab PATs into GitHub job lookup

When ASPECT_GITLAB_TOKEN is used from a GitHub Actions runner (the explicit non-GitLab-CI path this change enables), this call can return the user's GitLab PAT. A few lines later the feature calls resolve_build_url(ctx, existing_app_token = token), and on GitHub Actions that resolver treats existing_app_token as a GitHub App token and sends it to the GitHub jobs API as Authorization: Bearer ... before falling back. That leaks the GitLab token to GitHub in this supported cross-CI configuration; avoid passing explicit GitLab tokens into the GitHub URL resolver, or skip that resolver when auth_kind == "private_token".

Useful? React with 👍 / 👎.

@aspect-workflows

aspect-workflows Bot commented Jun 16, 2026

Copy link
Copy Markdown

✨ Aspect Workflows Tasks

📅 Tue Jun 16 04:01:29 UTC 2026

⚠️ 2 flagged tasks

  • ⚠️ delivery (delivery-gha-debug) · ⏱ 45.4s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (1 delivered · 2 warn · 3 skipped)
  • ⚠️ delivery (delivery-gha) · ⏱ 1m 16s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Delivery complete (1 delivered · 2 warn · 3 skipped)

✅ 14 successful tasks

  • ✅ build (build-gha-debug) · ⏱ 3m 43s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (165 built)
  • ✅ build (build-gha) · ⏱ 3m 45s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel build complete (165 built)
  • ✅ buildifier (buildifier-gha-debug) · ⏱ 32s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ buildifier (buildifier-gha) · ⏱ 41.3s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha-debug) · ⏱ 1m 40s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ format (format-gha) · ⏱ 1m 32s · 🐙 GitHub Actions · ☑️ Check
    💬 Format complete (clean)
  • ✅ gazelle (gazelle-gha-debug) · ⏱ 58.8s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-from-source-gha-debug) · ⏱ 2m 27s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-from-source-gha) · ⏱ 2m 39s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ gazelle (gazelle-gha) · ⏱ 36.1s · 🐙 GitHub Actions · ☑️ Check
    💬 Gazelle complete (clean)
  • ✅ lint (lint-gha-debug) · ⏱ 35.2s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ lint (lint-gha) · ⏱ 38.9s · 🐙 GitHub Actions · ☑️ Check
    💬 Lint complete (clean)
  • ✅ test (test-gha-debug) · ⏱ 4m · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)
  • ✅ test (test-gha) · ⏱ 4m 4s · ✨ Aspect · 🐙 GitHub Actions · ☑️ Check
    💬 Bazel test complete (25/25 passed · 25 cached)

🔁 Reproduce

⚠️ delivery (delivery-gha-debug · delivery-gha)

# --mode=always --track-state=false for off-runner with no state backend.
aspect delivery \
  --commit-sha=a2a298aaef8190ec6f57b03cd85e9f44838698ea \
  --mode=always \
  --track-state=false \
  --dry-run=true

Install aspect: docs.aspect.build/cli/install


⏱ Last updated Tue Jun 16 04:08:02 UTC 2026 · 📊 GitHub API quota 1,381/15,000 (9% used, resets in 52m, throttle 7×)
🚀 Powered by Aspect CLI (v0.0.0-dev)  |  Aspect Build · X · LinkedIn · YouTube

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant